package at.tugraz.hidipic.web;

import at.tugraz.hidipic.model.*;
import at.tugraz.hidipic.service.DataAccessService;
import at.tugraz.hidipic.web.propertyeditor.ProjectPropertyEditor;
import at.tugraz.hidipic.web.propertyeditor.UserPropertyEditor;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.validation.Valid;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomCollectionEditor;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping(value = "/researcher")
public class ResearcherController {

    private final Logger LOG = Logger.getLogger(ResearcherController.class);
    @Autowired
    private HibernateTemplate hibernateTemplate;
    @Autowired
    DataAccessService dataAccessService;

    @InitBinder()
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Set.class, "authorities", new CustomCollectionEditor(Set.class) {

            @Override
            protected Object convertElement(Object element) {
                if (element instanceof String) {
                    CustomGrantedAuthority cga = new CustomGrantedAuthority();
                    String elem = (String) element;
                    cga.setAuthority(elem);
                    return cga;
                }
                return element;
            }
        });
        binder.registerCustomEditor(Set.class, "methods", new CustomCollectionEditor(Set.class) {

            @Override
            protected Object convertElement(Object element) {
                if (element instanceof String) {
                    Method method = new Method();
                    String elem = (String) element;
                    method.setName(elem);
                    return method;
                }
                return element;
            }
        });
        binder.registerCustomEditor(Set.class, "researchers", new CustomCollectionEditor(Set.class) {

            @Override
            protected Object convertElement(Object element) {
                if (element instanceof String) {
                    User user = new User();
                    String elem = (String) element;
                    user.setUsername(elem);
                    return user;
                }
                return element;
            }
        });
        binder.registerCustomEditor(User.class, "projectLeader", new UserPropertyEditor());
        binder.registerCustomEditor(Project.class, "parent", new ProjectPropertyEditor());
    }

    /**
     * request for manage page
     * @return the redirect to the manage page
     */
    @RequestMapping(value = "/*", method = RequestMethod.GET)
    public ModelAndView handleRequest() {
        return new ModelAndView("redirect:/manage");
    }

    /**
     * request for deleting uploaded data
     * @param dataId
     * @return redirect to manage page
     */
    @RequestMapping(value = "/data/delete/{dataId}")
    public String deleteInputData(@PathVariable("dataId") String dataId) {
//        DataItem di = hibernateTemplate.get(DataItem.class, dataId);
//        if (di != null) {
//            try {
//                hibernateTemplate.delete(di);
//            } catch (Exception e) {
//                LOG.error(e);
//            }
//        }
        return "redirect:/manage";
    }

    /**
     * request for deleting a subproject
     * @param subProjectId
     * @return redirect to manage-page
     */
    @RequestMapping(value = "/subproject/delete/{subProjectId}", method = RequestMethod.GET)
    public ModelAndView deleteSubProject(@PathVariable("subProjectId") String subProjectId) {
//        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//        User u = hibernateTemplate.get(User.class, loggedIn.getUsername());
//        int projectId = -1;
//        try {
//            projectId = Integer.parseInt(subProjectId);
//        } catch (Exception e) {
//            LOG.error(e);
//        }
//        if (projectId >= 0) {
//            SubProject selectedProject = (SubProject) hibernateTemplate.get(SubProject.class, projectId);
//            if (selectedProject != null) {
//                try {
//                    if (selectedProject.getParent().getProjectLeader().getUsername().equals(u.getUsername())) {
//                        hibernateTemplate.delete(selectedProject);
//                    }
//                } catch (Exception e) {
//                    LOG.error(e);
//                }
//            }
//        }
        return handleRequest();
    }

    /**
     * request for adding a subproject
     * @return the model and view for the form
     */
    @RequestMapping(value = "/subproject/add", method = RequestMethod.GET)
    public ModelAndView addSubProject() {
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User u = hibernateTemplate.get(User.class, loggedIn.getUsername());
        ModelAndView mav = new ModelAndView("/researcher/subproject/add");
        SubProject subProject = new SubProject();
        List<User> researchers = dataAccessService.getAllUsersWithLevel(KDDConstants.RESEARCHER_ROLE);
        List<Project> projects = dataAccessService.getLeadProjectsForUser(u);
        mav.addObject("researcherList", researchers);
        mav.addObject("projects", projects);
        mav.addObject("subProject", subProject);
        return mav;
    }

    /**
     * request for adding a subproject
     * @param subProject
     * @param result
     * @return return redirect to manage page
     */
    @RequestMapping(value = "/subproject/add", method = RequestMethod.POST)
    private ModelAndView doAddSubProject(@ModelAttribute("subProject") @Valid SubProject subProject, BindingResult result) {
        if (!result.hasErrors()) {
            try {
                subProject.setCreationDate(new Date());
                subProject.setCreator((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal());
                hibernateTemplate.save(subProject);
                ModelAndView mav = handleRequest();
                return mav;
            } catch (Exception e) {
                LOG.error(e);
            }
        } else {
            ModelAndView mav = addSubProject();
            mav.addObject("subProject", subProject);
            return mav;
        }
        ModelAndView mav = handleRequest();
        return mav;
    }

    /**
     * request for showing the edit form of a subproject
     * @param subProjectId
     * @return redirect to manage page
     */
    @RequestMapping(value = "/subproject/edit/{subProjectId}", method = RequestMethod.GET)
    private ModelAndView editSubProject(@PathVariable("subProjectId") String subProjectId) {
        User loggedIn = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User u = hibernateTemplate.get(User.class, loggedIn.getUsername());
        ModelAndView mav = new ModelAndView("researcher/subproject/edit");
        int projectId = -1;
        try {
            projectId = Integer.parseInt(subProjectId);
        } catch (Exception e) {
            LOG.error(e);
        }
        if (projectId >= 0) {
            SubProject subProject = (SubProject) hibernateTemplate.get(SubProject.class, projectId);
            if (subProject != null && subProject.getParent().getProjectLeader().getUsername().equals(u.getUsername())) {
                List<User> researchers = dataAccessService.getAllUsersWithLevel(KDDConstants.RESEARCHER_ROLE);
                List<Project> projects = dataAccessService.getLeadProjectsForUser(u);
                mav.addObject("researcherList", researchers);
                mav.addObject("projects", projects);
                mav.addObject("subProject", subProject);
                return mav;
            }
        }
        mav = handleRequest();
        return mav;
    }

    /**
     * request for editing a subproject
     * @param projectId
     * @param subProject
     * @param result
     * @return redirect to manage-page
     */
    @RequestMapping(value = "/subproject/edit/{subProjectId}", method = RequestMethod.POST)
    private ModelAndView doEditProject(@PathVariable("subProjectId") String projectId, @ModelAttribute("subProject") @Valid SubProject subProject, BindingResult result) {
        int projId = -1;
        try {
            projId = Integer.parseInt(projectId);
        } catch (Exception e) {
            LOG.error(e);
        }
        if (projId >= 0) {
            subProject.setId(projId);
            if (!result.hasErrors()) {
                try {
                    SubProject updateProject = hibernateTemplate.get(SubProject.class, projId);
                    dataAccessService.updateSubProjectFromEdit(subProject, updateProject);
                    hibernateTemplate.merge(subProject);
                    ModelAndView mav = handleRequest();
                    return mav;
                } catch (Exception e) {
                    LOG.error(e);
                }
            } else {
                ModelAndView mav = editSubProject(projectId);
                mav.addObject("subProject", subProject);
                return mav;
            }
        }
        ModelAndView mav = handleRequest();
        return mav;
    }
}
